package org.flint.summary.javassist;

import javassist.*;
import javassist.bytecode.AccessFlag;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author flint92
 */
public class JavassistMain {

    public void DynamicGenerateClass() {
        ClassPool classPool = ClassPool.getDefault();
        // 创建类
        CtClass ctClass = classPool.makeClass("org.flint.summary.javassist.GenerateClass");
        // 让类实现java.lang.Cloneable接口
        ctClass.setInterfaces(new CtClass[]{classPool.makeInterface("java.lang.Cloneable")});

        try {
            // 获得一个类型为int，名称为id的字段
            CtField ctField = new CtField(CtClass.intType, "id", ctClass);
            // 设置为public类型
            ctField.setModifiers(AccessFlag.PUBLIC);
            // //将字段设置到类上
            ctClass.addField(ctField);
            //添加构造函数
            CtConstructor constructor = CtNewConstructor.make("public GeneratedClass(int pId){this.id=pId;}", ctClass);
            ctClass.addConstructor(constructor);
            //添加方法
            CtMethod helloM = CtNewMethod.make("public void hello(String des){ System.out.println(des);}", ctClass);
            ctClass.addMethod(helloM);

            // 将生成的.class文件写到磁盘
            ctClass.writeFile();

            Field[] fields = ctClass.toClass().getFields();
            System.out.println("属性名称：" + fields[0].getName() + "  属性类型：" + fields[0].getType());

        } catch (CannotCompileException | NotFoundException | IOException e) {
            // ignored
        }
    }

    @SuppressWarnings("unchecked")
    public void modifyPointMoveMethod() {
        ClassPool classPool = ClassPool.getDefault();

        try {
            CtClass clazz = classPool.getCtClass("org.flint.summary.javassist.Point");
            // 获取move方法
            CtMethod method = clazz.getDeclaredMethod("move");
            // 前置插入
            method.insertBefore("{System.out.println(\"deltaX: \" + $1); System.out.println(\"deltaY: \" + $2);}");
            // 后置插入
            method.insertAfter("{System.out.println(this.x);System.out.println(this.y);}");

            clazz.writeFile();

            // 通过反射调用
            Class c = clazz.toClass();
            Method move = c.getMethod("move", int.class, int.class);
            Constructor constructor = c.getConstructor(int.class, int.class);
            // 调用
            move.invoke(constructor.newInstance(1, 2), 1, 2);

        } catch (NotFoundException | CannotCompileException | IOException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            // ignored
        }
    }

    public static void main(String[] args) {
//        new JavassistMain().DynamicGenerateClass();

        new JavassistMain().modifyPointMoveMethod();
    }

}
